package edu.ntu.cloudroid.client;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;

import edu.ntu.cloudroid.model.data.AbstractData;
import edu.ntu.cloudroid.model.data.DetachedData;
import edu.ntu.cloudroid.model.policy.PolicyInfo;
import edu.ntu.cloudroid.nongui.com.AbstractResponse;
import edu.ntu.cloudroid.nongui.com.Communicator;
import edu.ntu.cloudroid.nongui.com.VitalDataRequestWithInputs;
import edu.ntu.cloudroid.nongui.com.VitalRequestWithFilteringFunction;

public class FunctionTester {
	public static void main(String[] args) throws Exception {
		String targetAddress = args[0];
		int targetPort = Integer.parseInt(args[1]);
		boolean standard = Boolean.parseBoolean(args[2]); 

		List<String> functions = Generator.generateFunctions(1);

		Communicator comm = new Communicator(null, targetAddress, targetPort);
		// init

		//System.out.println(comm.getData(new VitalDataRequestWithInputs("user_0@gmail.com", 50, 50)).getAccessDecision());
		Random rand = new Random(100);
		// start
		for (String function : functions) {
			//System.out.println("Setting function " + function);
			// set function
			/*for (int i = 0; i < 1000; i++) {
				String user = String.format("user_%d@gmail.com", i);
				comm.sendData(new PolicyInfo(user, (user + function).split(",")));
			}

			Thread.sleep(1000);*/

			//sendOnlyOne(comm, rand, standard, function);
			
			double hr = 100 * rand.nextDouble();
			double bp = 100 * rand.nextDouble();
			AbstractResponse data1 = comm.getData(new VitalRequestWithFilteringFunction("user_0@gmail.com", new PolicyInfo("user_0@gmail.com", ("user_0@gmail.com"+function).split(","))));
			AbstractResponse data2 = comm.getData(new VitalDataRequestWithInputs("user_0@gmail.com", hr, bp));
			
			
			System.out.println("data1");
			printData(data1);
			System.out.println("data2");
			printData(data2);
			
			//System.out.println("testing without XACML");
			// test without XACML
			//if (false)
			/*
			  for (int i = 0; i < 10; i++) {

				comm.getData(new VitalRequestWithFilteringFunction("user_0@gmail.com", new PolicyInfo("user_0@gmail.com", ("user_0@gmail.com"+function).split(","))));
				Thread.sleep(1000);
			}

			Thread.sleep(5000);

			System.out.println("testing with XACML");
			// test XACML

			for (int i = 0; i < 10; i++) {
				System.out.println(comm.getData(new VitalDataRequestWithInputs("user_0@gmail.com", hr, bp)).getAccessDecision());
				Thread.sleep(1000);
			} */

			//double hr = 100 * rand.nextDouble();
			//double bp = 100 * rand.nextDouble();


			//System.out.println(compareAbstractResponse(data1, data2));
			/*System.out.println("data1");
			System.out.println(data1.getAccessDecision());
			Map<String, Map<String, List<DetachedData>>> rData = data1.getReturnedData();
			
			for (Entry<String, Map<String, List<DetachedData>>> e : rData.entrySet()) {
				System.out.println(e.getKey());
				for (String k: e.getValue().keySet()) {
					System.out.printf("%s %s\n", k, e.getValue().get(k));
				}
			}
			
			System.out.println("data2");
			System.out.println(data2.getAccessDecision());
			rData = data2.getReturnedData();
			
			for (Entry<String, Map<String, List<DetachedData>>> e : rData.entrySet()) {
				System.out.println(e.getKey());
				for (String k: e.getValue().keySet()) {
					System.out.printf("%s %s\n", k, e.getValue().get(k));
				}
			}*/
		}
	}
	
	private static void printData(AbstractResponse response) {
		System.out.println(response.getAccessDecision());
		Map<String, Map<String, List<DetachedData>>> map = response.getReturnedData();
		
		for (Entry<String, Map<String, List<DetachedData>>> e : map.entrySet()) {
			System.out.println(e.getKey());
			for (String k: e.getValue().keySet()) {
				System.out.printf("%s %s\n", k, e.getValue().get(k));
			}
		}
	}

	private static void sendOnlyOne(Communicator comm, Random rand, boolean standard, String function) {
		for (int i = 0; i < 10; i++) {
			if (standard) {
				double hr = 100 * rand.nextDouble();
				double bp = 100 * rand.nextDouble();
				AbstractResponse data2 = comm.getData(new VitalDataRequestWithInputs("user_0@gmail.com", hr, bp));
			} else {
				AbstractResponse data1 = comm.getData(new VitalRequestWithFilteringFunction("user_0@gmail.com", new PolicyInfo("user_0@gmail.com", ("user_0@gmail.com"+function).split(","))));
			}
		}
	}

	private static String compareAbstractResponse(AbstractResponse data1, AbstractResponse data2) {
		//if (data1.equals(data2))
		//	return ok
		if (data1.getAccessDecision() != data2.getAccessDecision())
			return "differ on access decision";
		if (!data1.getRequesterId().equals(data2.getRequesterId()))
			return "differ on requester id";
		Map<String, Map<String, List<DetachedData>>> rData1 = data1.getReturnedData();
		Map<String, Map<String, List<DetachedData>>> rData2 = data2.getReturnedData();

		if (null != rData1) {
			if (null == rData2)
				return "2 is null";
			if (rData1.size() != rData2.size())
				return "differ on size: " + rData1.size() + " " + rData2.size();

			for (String key : rData1.keySet()) {
				Map<String, List<DetachedData>> map1 = rData1.get(key);
				Map<String, List<DetachedData>> map2 = rData2.get(key);
				if (null == map2)
					return key + " not in rData2";

				for (String key2 : map1.keySet()) {
					List<DetachedData> list1 = map1.get(key2);
					List<DetachedData> list2 = map2.get(key2);

					if (null == list2)
						return key2 + " not in map2";
					if (list1.size() != list2.size())
						return "lists at index " + key2 + " differ in size";
				}
			}
		} else {
			if (null != rData2)
				return "2 is not null";
		}

		return "OK";
	}
}
